
#ifdef GL_ES
precision mediump float;
#endif

#define TMIN .1
#define TMAX 20.
#define RAYMARCH_TIME 128
#define PRECISION .001
#define AA 2

#define PI 3.1415926535

uniform vec2 u_resolution;
uniform float u_time;

const vec3 translate=vec3(0.,0.,-2.);
const float radius=1.2;

vec2 fixUV(in vec2 c){
    return(2.*c-u_resolution.xy)/min(u_resolution.x,u_resolution.y);
}

mat3 rorate(float angle){
    float c= cos(angle);
    float s= sin(angle);
    return mat3(1.,0.,0.,0.,c,-s,0.,s,c);
}

float sdfSphere(in vec3 p){
    return length(p+translate)-radius;
}

float sdfCube(in vec3 p , vec3 b){
    vec3 d = abs(p)-b; 
    return length(max(d,0.))+min(max(d.x,max(d.y,d.z)),0.); 
}

float rayMarch(in vec3 ro,in vec3 rd){
    float t=TMIN;
    for(int i=0;i<RAYMARCH_TIME;i++){
        vec3 p=ro+t*rd;
        p=rorate(sin(u_time)*2.)*p;
        float d=sdfCube(p,vec3(.5,.5,.4));
       
        // if(d < PRECISION){break;}
        // if(t >= TMAX)  { break; }
        float isOut=step(0.,TMAX-t);
        float isAcc=step(0.,d-PRECISION);
        t+=d*isOut;
    }
    return t;
}

vec3 calcNormal(in vec3 p){
    float h=.0001;
    vec2 k=vec2(1.,-1.);
    return normalize(
        k.xyy*sdfSphere(p+k.xyy*h)+
        k.yyx*sdfSphere(p+k.yyx*h)+
        k.yxy*sdfSphere(p+k.yxy*h)+
        k.xxx*sdfSphere(p+k.xxx*h));
    }
    
vec3 render(vec2 uv){
    vec3 color=vec3(0.);
    vec3 ro=vec3(0.,0.,-1.5);
    vec3 rd=normalize(vec3(uv,0.)-ro);
    float t=rayMarch(ro,rd);
    if(t<TMAX){
        vec3 p=ro+t*rd;
        vec3 norm=calcNormal(p);
        vec3 light=vec3(cos(u_time),2.,sin(u_time));
        float diff =dot(normalize(light-p),norm);
        diff = clamp(diff,0.0,1.0);
        
        float ambt=.031;
        
        float powRatio=12.;
        vec3 viewDir=normalize(vec3(uv,0.)-p);
        vec3 reflectDir=reflect(-light,norm);
        float spec=pow(max(dot(viewDir,reflectDir),0.),powRatio);
        spec = clamp(spec,0.0,1.0);
        
        color+=vec3(.4627,.6196,.5569)*diff;
        color+=vec3(0.1)*spec;
        color+=vec3(ambt);
    }
    
    return sqrt(color);
}
    
vec3 anti_align(){
    vec3 color=vec3(0.);
    for(int m=0;m<AA;m++){
        for(int n=0;n<AA;n++){
            vec2 offset=2.*(vec2(float(m),float(n))/float(AA)-.5);
            vec2 uv=fixUV(gl_FragCoord.xy+offset);
            color+=render(uv);
        }
    }
    return color;
}
    
    void main(){
        
        vec2 uv=fixUV(gl_FragCoord.xy);
        vec3 color=vec3(0.);
        
        color += anti_align( ); 
        // color=render(uv);
        
        gl_FragColor=vec4(vec3(color)/float(AA*AA),1.);
    }